package com.piece.admin.support;

import com.piece.admin.model.TbSysDict;
import com.piece.admin.service.TbSysDictService;
import com.piece.core.framework.annotation.translate.DicTranslate;
import com.piece.core.framework.annotation.translate.SelectTranslate;
import com.piece.core.framework.enums.LocalType;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.support.dto.UserDetailDTO;
import com.piece.core.framework.support.response.Select;
import com.piece.core.framework.util.basic.SpringUtil;
import com.piece.core.framework.util.collection.CollectionUtil;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.framework.util.cache.CacheFactory;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class TranslateEntity {

    @Resource
    protected CacheFactory cacheFactory;

    @Resource
    protected TbSysDictService tbSysDictService;

    /**
     * 实体对象特殊属性赋值
     */
    public void setEntityInfo(Object bean) {
        setEntityInfo(bean, false);
    }

    /**
     * 实体对象特殊属性赋值
     */
    public void setEntityInfo(Object bean, boolean cache) {
        Field[] fields = bean.getClass().getDeclaredFields();
        String dicType, dicLabel, proxy, target;
        Object dicValue;
        Object fieldValue;
        LocalType dicLan;
        boolean needUser;
        boolean hasCache;
        TbSysDict dic;
        List<TbSysDict> dict_list;
        DicTranslate dicTranslate;
        SelectTranslate selectTranslate;
        String[] beanMethods;
        String beanId, methodName;
        for (int col = 0; col < fields.length; col++) {
            Field field = fields[col];
            hasCache = false;
            try {
                fieldValue = BeanUtil.getFieldValue(bean, field.getName());
                // DicTranslate 赋值
                if (field.isAnnotationPresent(DicTranslate.class)) {
                    dicTranslate = field.getAnnotation(DicTranslate.class);
                    if (cache && StringUtil.isEmpty(dicTranslate.cache())) {
                        continue;
                    }
                    dicType = dicTranslate.dicType();
                    proxy = dicTranslate.proxy();

                    if (StringUtil.isNotEmpty(dicTranslate.source())) {
                        dicValue = BeanUtil.getFieldValue(bean, dicTranslate.source());
                    } else {
                        dicValue = fieldValue;
                    }
                    if (StringUtil.isNotEmpty(dicTranslate.target())) {
                        target = dicTranslate.target();
                    } else {
                        target = field.getName();
                    }

                    dicLan = dicTranslate.language();
                    needUser = dicTranslate.checkLogin();
                    if (StringUtil.isNotEmpty(dicTranslate.cache())) {
                        Object value = cacheFactory.get().get(dicTranslate.cache() + Convert.toStr(fieldValue), BeanUtil.getFieldByFieldName(bean.getClass(), target).getClass());
                        if (null != value) {
                            BeanUtil.setFieldValue(bean, target, value);
                            dicValue = value;
                            hasCache = true;
                        }
                    }
                    if (StringUtil.isNotEmpty(dicType) && !hasCache) {
                        dic = tbSysDictService.findByGroupValue(dicType, Convert.toStr(dicValue));
                        if (null != dic) {
                            switch (dicLan) {
                                case EN:
                                    dicLabel = dic.getDictLabelEn();
                                    break;
                                case CN:
                                default:
                                    dicLabel = dic.getDictLabel();
                            }

                            BeanUtil.setFieldValue(bean, target, dicLabel);
                            dicValue = dicLabel;
                        } else {
                            dict_list = tbSysDictService.findByGroupValue(dicType, Arrays.asList(Convert.toStrArray(Convert.toStr(dicValue))));
                            if (dict_list != null && dict_list.size() > 0) {
                                dicValue = transString(dict_list, dicLan);
                                BeanUtil.setFieldValue(bean, target, dicValue);
                            }
                        }
                    } else if (StringUtil.isNotEmpty(proxy) && !hasCache) {
                        beanMethods = proxy.split("[.]");
                        beanId = beanMethods[0];
                        methodName = beanMethods[1];
                        Object serviceBean = SpringUtil.getBean(beanId);
                        if (needUser) {
                            UserDetailDTO user = (UserDetailDTO) SecurityContextHolder.getContext().getAuthentication().getDetails();
                            Method invokeMethod = serviceBean.getClass().getDeclaredMethod(methodName, UserDetailDTO.class, dicValue.getClass());
                            dicValue = invokeMethod.invoke(serviceBean, user, dicValue);
                        } else {
                            Method invokeMethod = serviceBean.getClass().getDeclaredMethod(methodName, dicValue.getClass());
                            dicValue = invokeMethod.invoke(serviceBean, dicValue);
                        }
                        BeanUtil.setFieldValue(bean, target, dicValue);
                    }

                    // 放入缓存
                    if (cache && !hasCache) {
                        cacheFactory.get().set(dicTranslate.cache() + Convert.toStr(fieldValue), dicValue);
                    }
                }

                // SelectTranslate 赋值
                if (field.isAnnotationPresent(SelectTranslate.class)) {
                    selectTranslate = field.getAnnotation(SelectTranslate.class);
                    if (cache && StringUtil.isEmpty(selectTranslate.cache())) {
                        continue;
                    }

                    proxy = selectTranslate.proxy();
                    dicType = selectTranslate.dicType();
                    dicValue = Convert.toStr(BeanUtil.getFieldValue(bean, selectTranslate.target()), null);
                    dicLan = selectTranslate.language();

                    if (StringUtil.isNotEmpty(selectTranslate.cache())) {
                        List<Select.Entity> value = (List<Select.Entity>) cacheFactory.get().getList(selectTranslate.cache() + Convert.toStr(fieldValue));
                        if (CollectionUtil.isNotEmpty(value)) {
                            BeanUtil.setFieldValue(bean, field.getName(), value);
                            dicValue = value;
                            hasCache = true;
                        }
                    }
                    if (StringUtil.isNotEmpty(dicType) && !hasCache) {
                        dict_list = tbSysDictService.findByGroupValue(dicType, Arrays.asList(Convert.toStrArray(Convert.toStr(dicValue))));
                        if (CollectionUtil.isNotEmpty(dict_list)) {
                            dicValue = transSelect(dict_list, dicLan);
                            BeanUtil.setFieldValue(bean, field.getName(), dicValue);
                        }
                    } else if (StringUtil.isNotEmpty(proxy) && !hasCache) {
                        beanMethods = proxy.split("[.]");
                        beanId = beanMethods[0];
                        methodName = beanMethods[1];
                        Object serviceBean = SpringUtil.getBean(beanId);
                        Method invokeMethod = serviceBean.getClass().getDeclaredMethod(methodName, dicValue.getClass());
                        dicValue = invokeMethod.invoke(serviceBean, dicValue);
                        BeanUtil.setFieldValue(bean, field.getName(), dicValue);
                    }

                    // 放入缓存
                    if (cache && !hasCache) {
                        cacheFactory.get().rightPush(selectTranslate.cache() + Convert.toStr(fieldValue), dicValue);
                    }
                }
            } catch(Exception e){
                // log.error("setEntityInfo方法异常：{}", e.getMessage());
            }
        }
    }

    /**
     * 转换下拉菜单列表
     */
    public List<Select.Entity> transSelect(List<TbSysDict> dict_list, LocalType local) {
        List<Select.Entity> result = new ArrayList<>();
        Select select = Select.builder().build();
        Select.Entity temp;
        String dicLabel;
        for (TbSysDict dic : dict_list) {
            switch (local) {
                case EN:
                    dicLabel = dic.getDictLabelEn();
                    break;
                case CN:
                default:
                    dicLabel = dic.getDictLabel();
            }

            temp = select.new Entity(dic.getDictValue(), dicLabel);
            result.add(temp);
        }
        return result;
    }

    /**
     * 转换字典列表
     */
    public String transString(List<TbSysDict> dict_list, LocalType local) {
        String result = "", dicLabel;
        for (TbSysDict dic : dict_list) {
            switch (local) {
                case EN:
                    dicLabel = dic.getDictLabelEn();
                    break;
                case CN:
                default:
                    dicLabel = dic.getDictLabel();
            }

            result += "," + dicLabel;
        }

        if (result.length() > 0) {
            return result.substring(1);
        }
        return result;
    }
}
